package com.ekalenchuk.module.controllers.admin;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import javax.validation.Valid;
import javax.xml.bind.ValidationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.ekalenchuk.module.constants.PageConstants;
import com.ekalenchuk.module.domain.Article;
import com.ekalenchuk.module.dto.article.ArticleDTO;
import com.ekalenchuk.module.service.ArticleService;
import com.ekalenchuk.module.utils.ConvertUtils;

@Controller
public class ManageArticleController implements Serializable {

	private static final String MODEL_ATTRIBUTE_ARTICLES = "articles";

	public static final String ATTRIBUTE_MANAGE_ARTICLE = "manageArticle";

	private static final long serialVersionUID = 2352987295392960374L;

	private static final Logger logger = LoggerFactory.getLogger(ManageArticleController.class);

	@Autowired
	private ArticleService articleService;

	@RequestMapping(value = "/admin/add-article", method = RequestMethod.GET)
	public String viewAddArticlePage(Model model) {
		putArticleDTOAttibute(model);
		return PageConstants.ADMIN_ADD_ARTICLE;
	}

	@RequestMapping(value = "/admin/add-article", method = RequestMethod.POST)
	public String postAddArticle(@Valid @ModelAttribute(ATTRIBUTE_MANAGE_ARTICLE) ArticleDTO articleDTO, BindingResult result, Model model) {
		logger.info(String.format("Submitted values: \narticle: %s;\ntext: %s;\ntags:%s", articleDTO.getTitle(), articleDTO.getText(), articleDTO.getTags()));
		if (!result.hasErrors()) {
			saveArticle(articleDTO);

			return PageConstants.REDIRECT_AMDIN_ADD_ARTICLE;
		} else {
			return PageConstants.ADMIN_ADD_ARTICLE;
		}

	}

	@RequestMapping(value = "/admin/manage-articles", method = RequestMethod.GET)
	public String manageArticlesPage(final Model model) {
		List<Article> articles = articleService.getArticles();
		model.addAttribute(MODEL_ATTRIBUTE_ARTICLES, articles);
		return PageConstants.ADMIN_MANAGE_ARTICLES;

	}

	@RequestMapping(value = "/admin/delete-article", method = RequestMethod.POST)
	public String deleteArticle(Long articleId, Model model) {
		if (articleId != null) {
			articleService.removeArticle(articleId);
		}
		return PageConstants.ADMIN_MANAGE_ARTICLES;
	}

	@RequestMapping(value = "/admin/edit-article", method = RequestMethod.POST)
	public String editArticle(Long articleId) {
		return "redirect:/admin/edit-article/" + articleId;
	}

	@RequestMapping(value = "/admin/edit-article/{articleId}", method = RequestMethod.GET)
	public String editArticlePage(@PathVariable("articleId") String articleId, Model model) throws ValidationException {
		validateArticleId(articleId);
		Article article = articleService.getArticle(new Long(articleId));
		putArticleDTOAttibute(model, ConvertUtils.convertArticleToArticleDTO(article));
		return "edit-article.page";
	}

	private void validateArticleId(final String articleId) throws ValidationException {
		try {
			Long.parseLong(articleId);
		} catch (NumberFormatException ex) {
			logger.error("Article ID should be a numeric. ", ex);
			throw new ValidationException("Article id should be a numeric.");
		}

	}

	@RequestMapping(value = "/admin/edit-article/{articleId}", method = RequestMethod.POST)
	public String editArticlePage(@PathVariable("articleId") String articleId, @Valid @ModelAttribute(ATTRIBUTE_MANAGE_ARTICLE) ArticleDTO articleDTO, BindingResult result, Model model) {
		logger.info(String.format("Submitted values: \narticle: %s;\ntext: %s;\ntags:%s", articleDTO.getTitle(), articleDTO.getText(), articleDTO.getTags()));
		if (!result.hasErrors()) {
			saveArticle(articleDTO);

			return PageConstants.REDIRECT_ADMIN_MANAGE_ARTICLES;
		} else {
			return "/admin/edit-article/" + articleId;
		}

	}

	private void saveArticle(ArticleDTO articleDTO) {
		Article createdArticle = ConvertUtils.convertArticleDtoToArticle(articleDTO);
		createdArticle.setCreated(new Date());
		articleService.save(createdArticle);

	}

	private void putArticleDTOAttibute(final Model model) {
		putArticleDTOAttibute(model, new ArticleDTO());
	}

	private void putArticleDTOAttibute(final Model model, final ArticleDTO articleDTO) {
		model.addAttribute(ATTRIBUTE_MANAGE_ARTICLE, articleDTO);
	}

}
